﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;

namespace Common
{
    public static class AddressHelper
    {
        private const bool resolveNames = true;
        private static CountdownEvent countdown;
        private static int upCount;
        private static readonly object lockObj = new object();

        public static IPAddress GetLocalIP(string HostName)
        {
            return Dns.GetHostAddresses(HostName).First(x => x.AddressFamily == AddressFamily.InterNetwork);
        }

        public static void PrintActiveHosts()
        {
            countdown = new CountdownEvent(1);
            var sw = new Stopwatch();
            sw.Start();
            string ipBase = "192.168.1.";
            for (int i = 1; i < 255; i++)
            {
                string ip = ipBase + i.ToString();

                var p = new Ping();
                p.PingCompleted += p_PingCompleted;
                countdown.AddCount();
                p.SendAsync(ip, 100, ip);
            }
            countdown.Signal();
            countdown.Wait();
            sw.Stop();
            var span = new TimeSpan(sw.ElapsedTicks);
            Console.WriteLine("Took {0} milliseconds. {1} hosts active.", sw.ElapsedMilliseconds, upCount);
        }

        private static void p_PingCompleted(object sender, PingCompletedEventArgs e)
        {
            var ip = (string) e.UserState;
            if (e.Reply != null && e.Reply.Status == IPStatus.Success)
            {
                if (resolveNames)
                {
                    string name;
                    try
                    {
                        IPHostEntry hostEntry = Dns.GetHostEntry(ip);
                        name = hostEntry.HostName;
                    }
                    catch (SocketException ex)
                    {
                        name = "?";
                    }
                    Console.WriteLine("{0} ({1}) is up: ({2} ms)", ip, name, e.Reply.RoundtripTime);
                }
                lock (lockObj)
                {
                    upCount++;
                }
            }
            else if (e.Reply == null)
            {
                Console.WriteLine("Pinging {0} failed. (Null Reply object?)", ip);
            }
            countdown.Signal();
        }


        public static string GetPublicIP()
        {
            //TODO: use for internet connections
            String direction = "";
            WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
            using (WebResponse response = request.GetResponse())
            using (var stream = new StreamReader(response.GetResponseStream()))
            {
                direction = stream.ReadToEnd();
            }

            //Search for the ip in the html
            int first = direction.IndexOf("Address: ") + 9;
            int last = direction.LastIndexOf("</body>");
            direction = direction.Substring(first, last - first);
            return direction;
        }
    }
}